package top.cardone.data.jdbc.dao.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.NonNull;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import top.cardone.context.ApplicationContextHolder;
import top.cardone.core.util.func.Func2;
import top.cardone.core.util.func.Func3;
import top.cardone.data.dao.PageDao;
import top.cardone.data.support.PageSupport;
import top.cardone.data.support.PageableSupport;

import java.util.List;
import java.util.Map;

/**
 * @author yao hai tao
 * @date 2015/8/26
 */
public class PageDaoImpl extends SimpleDaoImpl implements PageDao {
    @Override
    public Page<Map<String, Object>> pageByFunc(@NonNull Func2 func, Object page) {
        return (Page<Map<String, Object>>) func.func(this, page);
    }

    @Override
    public Page<Map<String, Object>> pageByFuncId(@NonNull String funcId, Object page) {
        return this.pageByFunc(ApplicationContextHolder.getBean(Func2.class, funcId), page);
    }

    @Override
    public Page<Map<String, Object>> page(@NonNull String countSqlFilePath, @NonNull String findListSqlFilePath, Map<String, ?> page) {
        final long totalSize = this.readOne(Long.class, countSqlFilePath, page);

        if (totalSize < 1) {
            return ApplicationContextHolder.getBean(PageSupport.class).newPage(Lists.newArrayList(), page, totalSize);
        }

        Pageable pageable = ApplicationContextHolder.getBean(PageableSupport.class).newPageable(page);

        Map<String, Object> newPage = Maps.newHashMap(page);

        newPage.put("pageNumber", pageable.getPageNumber());
        newPage.put("pageSize", pageable.getPageSize());
        newPage.put("offset", pageable.getOffset());

        List<Map<String, Object>> findList = this.findList(findListSqlFilePath, newPage);

        return ApplicationContextHolder.getBean(PageSupport.class).newPage(findList, page, totalSize);
    }

    @Override
    public Page<Map<String, Object>> pageBySqlFileName(String countSqlFileName, String findListSqlFileName, Object page) {
        return this.page(this.getSqlFilePath(countSqlFileName), this.getSqlFilePath(findListSqlFileName), this.toMap(page, "page"));
    }

    @Override
    public <P> Page<P> pageByFunc(@NonNull Class<P> mappedClass, @NonNull Func3 func, Object page) {
        return (Page<P>) func.func(mappedClass, this, page);
    }

    @Override
    public <P> Page<P> pageByFuncId(@NonNull Class<P> mappedClass, @NonNull String funcId, Object page) {
        return this.pageByFunc(mappedClass, ApplicationContextHolder.getBean(Func3.class, funcId), page);
    }

    @Override
    public <P> Page<P> page(@NonNull Class<P> mappedClass, @NonNull String countSqlFilePath, @NonNull String
            findListSqlFilePath, Map<String, ?> page) {
        final long totalSize = this.readOne(Long.class, countSqlFilePath, page);

        if (totalSize < 1) {
            return ApplicationContextHolder.getBean(PageSupport.class).newPage(Lists.newArrayList(), page, totalSize);
        }

        Pageable pageable = ApplicationContextHolder.getBean(PageableSupport.class).newPageable(page);

        Map<String, Object> newPage = Maps.newHashMap(page);

        newPage.put("pageNumber", pageable.getPageNumber());
        newPage.put("pageSize", pageable.getPageSize());
        newPage.put("offset", pageable.getOffset());

        List<P> findList = this.findList(mappedClass, findListSqlFilePath, newPage);

        return ApplicationContextHolder.getBean(PageSupport.class).newPage(findList, page, totalSize);
    }

    @Override
    public <P> Page<P> pageBySqlFileName(Class<P> mappedClass, String countSqlFileName, String findListSqlFileName, Object page) {
        return this.page(mappedClass, this.getSqlFilePath(countSqlFileName), this.getSqlFilePath(findListSqlFileName), this.toMap(page, "page"));
    }
}